home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / strategy / vga_card.000 / vga_cardgames-1.3.1.tar / vga_cardgames / spider.c < prev    next >
C/C++ Source or Header  |  1994-04-25  |  10KB  |  578 lines

  1. /*
  2.  * Spider
  3.  *
  4.  * Copyright (C) Evan Harris, 1991, 1993, 1994
  5.  *
  6.  * Permission is granted to freely redistribute and modify this code,
  7.  * providing the author(s) get credit for having written it.
  8.  */
  9.  
  10. #include "spider.h"
  11. #include <stdlib.h>
  12.  
  13.  
  14. #define U_MOVE            1
  15. #define U_MOVEOFF        2
  16. #define U_MOVE_EXPOSE        3
  17. #define U_MOVEOFF_EXPOSE    4
  18. #define U_FROMSTOCK        5
  19.  
  20. struct undo {
  21.     unsigned char type;
  22.     unsigned char card;
  23.     short from;
  24.     struct undo    *next;
  25. };
  26.  
  27.  
  28. unsigned char    column[COLUMNS];        /* First card of column */
  29. unsigned char    stock;
  30. short        cards[NUMCARDS];        /* Positions of cards */
  31. unsigned char    next[NUMCARDS];            /* Card underneath */
  32. unsigned char    hidden[NUMCARDS];        /* Cards which are face down */
  33. unsigned char    foundation[NUMSUITS];
  34. struct undo    *undoinfo = NULL;
  35.  
  36.  
  37. void main(int argc, char **argv)
  38. {
  39.     short cmd, dest;
  40.  
  41.     InitDisplay(argc, argv);
  42.  
  43.     InitRandom(NEW);
  44.     Deal();
  45.  
  46.     for (;;) {
  47.     cmd = GetCmd();
  48.     if (cmd == QUIT) {
  49.         EndDisplay();
  50.         exit(0);
  51.     }
  52.     else if (cmd == NEWGAME) {
  53.         InitRandom(NEW);
  54.         Deal();
  55.     }
  56.     else if (cmd == RESTART) {
  57.         InitRandom(LAST);
  58.         Deal();
  59.     }
  60.     else if (cmd == FROMSTOCK) {
  61.         FromStock();
  62.     }
  63.     else if (cmd == UNDO) {
  64.         Undo();
  65.     }
  66.     else if (ISCARD(NOHINT(cmd))) {
  67.         dest = FindDest(cmd);
  68.         if (dest != NOPOSN)
  69.         MakeMove((unsigned char)NOHINT(cmd), dest);
  70.     }
  71.     }
  72.  
  73.     /* Never reached */
  74. }
  75.  
  76.  
  77. void Deal()
  78. {
  79.     unsigned char i, j;
  80.     unsigned char row, col;
  81.     short r, lastr = 0;
  82.     struct undo *u;
  83.  
  84.     /* Initialise the deck */
  85.     for (i = 0; i < NUMCARDS; i++) {
  86.     cards[i] = NOPOSN;
  87.     next[i] = NOCARD;
  88.     }
  89.     /* Initialise foundations */
  90.     for (i = 0; i < NUMSUITS; i++) {
  91.     foundation[i] = 0;
  92.     }
  93.         
  94.     /* Remove undo information */
  95.     while (undoinfo) {
  96.     u = undoinfo->next;
  97.     free(undoinfo);
  98.     undoinfo = u;
  99.     }
  100.  
  101.     /* Deal the deck */
  102.     row = 0;
  103.     col = 0;
  104.     for (i = 0; i < NUMCARDS; i++) {
  105.     r = Random(NUMCARDS - i);
  106.     for (j = 0; j < NUMCARDS && r >= 0; j++) {
  107.         if (cards[j] == NOPOSN)
  108.         r--;
  109.     }
  110.     r = j - 1;
  111.  
  112.     cards[r] = POSN(col, row);
  113.     if (col != STOCK) {
  114.         if (row == 0)
  115.         column[col] = r;
  116.         else
  117.         next[lastr] = r;
  118.         lastr = r;
  119.  
  120.         if ((col < 4 && row < 5) || (row < 4)) {
  121.         hidden[r] = 1;
  122.         row++;
  123.         }
  124.         else {
  125.         hidden[r] = 0;
  126.         col++; 
  127.         row = 0;
  128.         }
  129.     }
  130.     else {
  131.         if (row == 0)
  132.         stock = r;
  133.         else
  134.         next[lastr] = r;
  135.         lastr = r;
  136.         hidden[r] = 0;
  137.         row++;
  138.     }
  139.     }
  140.     for (i = 0; i < COLUMNS; i++)
  141.     DisplayColumn((short)i);
  142.     DisplayFoundations();
  143.     DisplayStockPile();
  144.  
  145.     return;
  146. }
  147.  
  148.  
  149. short FindDest(short card)
  150. {
  151.     unsigned char i, c;
  152.     short first = -1;
  153.  
  154.     c = next[NOHINT(card)];
  155.     i = 1;
  156.     while (c != NOCARD) {
  157.     if (SUIT(c) != SUIT(NOHINT(card)) || TYPE(c) != TYPE(NOHINT(card)) - i) {
  158.         return NOPOSN;
  159.     }
  160.     c = next[c];
  161.     i++;
  162.     }
  163.  
  164.     if (HASHINT(card))
  165.     return FindHintedDest((short)NOHINT(card), (short)HINT(card));
  166.  
  167.     if (CanMoveOff((unsigned char)card))
  168.     return MOVEOFF;
  169.  
  170.     c = column[COL(cards[card])];
  171.     if (c != card) {
  172.     while (next[c] != card)
  173.         c = next[c];
  174.     if (!hidden[c] && TYPE(c) == TYPE(card) + 1 && SUIT(c) == SUIT(card)) {
  175.         return NOPOSN;
  176.     }
  177.     }
  178.  
  179.     if (TYPE(card) != KING) {
  180.     for (i = 0; i < COLUMNS; i++) {
  181.         if (i != COL(cards[card]) && column[i] != NOCARD) {
  182.         c = column[i];
  183.         while (next[c] != NOCARD)
  184.             c = next[c];
  185.         if (TYPE(c) == TYPE(card) + 1) {
  186.             if (SUIT(c) == SUIT(card)) {
  187.             return (short)POSN(COL(cards[c]), ROW(cards[c]) + 1);
  188.             }
  189.             else if (first == -1)
  190.             first = c;
  191.         }
  192.         }
  193.     }
  194.     if (first != -1) {
  195.         return (short)POSN(COL(cards[first]), ROW(cards[first]) + 1);
  196.     }
  197.     }
  198.     if (ROW(cards[card]) == 0) {
  199.     return NOPOSN;
  200.     }
  201.     for (i = 0; i < COLUMNS; i++) {
  202.     if (column[i] == NOCARD) {
  203.         return (short)POSN(i, 0);
  204.     }
  205.     }
  206.  
  207.     return NOPOSN;
  208. }
  209.  
  210.  
  211. short FindHintedDest(short card, short hint)
  212. {
  213.     unsigned char c;
  214.  
  215.     if (hint == FOUNDATION) {
  216.     if (CanMoveOff((unsigned char)card))
  217.         return MOVEOFF;
  218.     else
  219.         return NOPOSN;
  220.     }
  221.  
  222.     if (TYPE(card) != KING && hint != COL(cards[card])) {
  223.     c = column[hint];
  224.     if (c != NOCARD) {
  225.         while (next[c] != NOCARD)
  226.         c = next[c];
  227.         if (TYPE(c) == TYPE(card) + 1) {
  228.         return (short)POSN(COL(cards[c]), ROW(cards[c]) + 1);
  229.         }
  230.     }
  231.     }
  232.     if (ROW(cards[card]) == 0)
  233.     return NOPOSN;
  234.     if (column[hint] == NOCARD)
  235.     return (short)POSN(hint, 0);
  236.  
  237.     return NOPOSN;
  238. }
  239.  
  240.  
  241. void MakeMove(unsigned char card, short dest)
  242. {
  243.     short col, row, oldcol;
  244.     unsigned char c, i;
  245.     unsigned char h = 0;
  246.  
  247.     if (dest == MOVEOFF) {
  248.     MoveOff(card);
  249.     return;
  250.     }
  251.  
  252.     col = COL(dest);
  253.     row = ROW(dest);
  254.     oldcol = -1;
  255.  
  256.     for (i = 0; oldcol == -1 && i < COLUMNS; i++) {
  257.     if (column[i] == card) {
  258.         column[i] = NOCARD;
  259.         oldcol = i;
  260.     }
  261.     }
  262.     for (i = 0; oldcol == -1 && i < NUMCARDS; i++) {
  263.     if (next[i] == card) {
  264.         if (hidden[i]) {
  265.         hidden[i] = 0;
  266.         h = 1;
  267.         }
  268.         next[i] = NOCARD;
  269.         oldcol = COL(cards[i]);
  270.     }
  271.     }
  272.  
  273.     if (h)
  274.     AddUndo(U_MOVE_EXPOSE, card, cards[card]);
  275.     else
  276.     AddUndo(U_MOVE, card, cards[card]);
  277.  
  278.     if (row > 0) {
  279.     c = column[col];
  280.     while (next[c] != NOCARD)
  281.         c = next[c];
  282.     next[c] = card;
  283.     }
  284.     else
  285.     column[col] = card;
  286.     while (card != NOCARD) {
  287.     cards[card] = POSN(col, row++);
  288.     card = next[card];
  289.     }
  290.  
  291.     DisplayColumn(oldcol);
  292.     DisplayColumn(col);
  293.  
  294.     return;
  295. }
  296.  
  297.  
  298. void FromStock()
  299. {
  300.     unsigned char c, col, row;
  301.  
  302.     if (stock != NOCARD) {
  303.     for (col = 0; col < COLUMNS; col++) {
  304.         if (column[col] == NOCARD) {
  305.         return;
  306.         }
  307.     }
  308.     for (col = 0; col < COLUMNS; col++) {
  309.         c = column[col];
  310.         row = 1;
  311.         while (next[c] != NOCARD) {
  312.         c = next[c];
  313.         row++;
  314.         }
  315.         next[c] = stock;
  316.         stock = next[stock];
  317.         cards[next[c]] = POSN(col, row);
  318.         next[next[c]] = NOCARD;
  319.  
  320.         DisplayColumn((short)col);
  321.     }
  322.  
  323.     if (stock == NOCARD)
  324.         DisplayStockPile();
  325.  
  326.     AddUndo(U_FROMSTOCK, 0, 0);
  327.     }
  328.  
  329.     return;
  330. }
  331.  
  332.  
  333. void MoveOff(unsigned char card)
  334. {
  335.     unsigned char c, lastc;
  336.     unsigned char h = 0;
  337.     short oldcol;
  338.  
  339.     oldcol = COL(cards[card]);
  340.     c = column[oldcol];
  341.     lastc = NOCARD;
  342.     while (hidden[c]) {
  343.     lastc = c;
  344.     c = next[c];
  345.     }
  346.  
  347.     for (;;) {
  348.     while (c != NOCARD && TYPE(c) != KING && SUIT(c) != SUIT(card)) {
  349.         lastc = c;
  350.         c = next[c];
  351.     }
  352.     if (CheckFullTerminatingSuit(c)) {
  353.         if (lastc == NOCARD)
  354.         column[oldcol] = NOCARD;
  355.         else {
  356.         next[lastc] = NOCARD;
  357.         if (hidden[lastc]) {
  358.             hidden[lastc] = 0;
  359.             h = 1;
  360.         }
  361.         }
  362.         if (h)
  363.         AddUndo(U_MOVEOFF_EXPOSE, c, cards[c]);
  364.         else
  365.         AddUndo(U_MOVEOFF, c, cards[c]);
  366.         while (c != NOCARD) {
  367.         cards[c] = POSN(FOUNDATION, 0);
  368.         c = next[c];
  369.         }
  370.  
  371.         if (foundation[SUIT(card)])
  372.         foundation[SUIT(card) + 4] = 1;
  373.         else
  374.         foundation[SUIT(card)] = 1;
  375.         DisplayFoundations();
  376.         DisplayColumn(oldcol);
  377.  
  378.         return;
  379.     }
  380.     else {
  381.         lastc = c;
  382.         c = next[c];
  383.     }
  384.     }
  385. }
  386.  
  387.  
  388. short CanMoveOff(unsigned char card)
  389. {
  390.     unsigned char c;
  391.  
  392.     c = column[COL(cards[card])];
  393.     while (hidden[c])
  394.     c = next[c];
  395.     while (c != NOCARD) {
  396.     while (c != NOCARD && TYPE(c) != KING && SUIT(c) != SUIT(card))
  397.         c = next[c];
  398.     if (CheckFullTerminatingSuit(c)) 
  399.         return TRUE;
  400.     else
  401.         c = next[c];
  402.     }
  403.     return FALSE;
  404. }
  405.  
  406.  
  407. short CheckFullTerminatingSuit(unsigned char card)
  408. {
  409.     unsigned char c;
  410.     short type;
  411.  
  412.     c = card;
  413.     type = KING;
  414.     while (c != NOCARD && SUIT(c) == SUIT(card) && TYPE(c) == type) {
  415.     c = next[c];
  416.     type--;
  417.     }
  418.  
  419.     if (c == NOCARD && type == ACE - 1)
  420.     return TRUE;
  421.     else
  422.     return FALSE;
  423. }
  424.  
  425.  
  426. void AddUndo(unsigned char type, unsigned char card, short from)
  427. {
  428.     struct undo *undo;
  429.  
  430.     undo = (struct undo *)malloc(sizeof(struct undo));
  431.     undo->type = type;
  432.     undo->card = card;
  433.     undo->from = from;
  434.     undo->next = undoinfo;
  435.     undoinfo = undo;
  436.  
  437.     return;
  438. }
  439.  
  440.  
  441. void Undo()
  442. {
  443.     struct undo *undo = undoinfo;
  444.  
  445.     if (undo == NULL)
  446.     return;
  447.  
  448.     switch (undo->type) {
  449.       case U_MOVE:
  450.     UndoMove(undo->card, (short)COL(undo->from), 0);
  451.     break;
  452.       case U_MOVE_EXPOSE:
  453.     UndoMove(undo->card, (short)COL(undo->from), 1);
  454.     break;
  455.       case U_MOVEOFF:
  456.     UndoMoveOff(undo->card, (short)COL(undo->from), 0);
  457.     break;
  458.       case U_MOVEOFF_EXPOSE:
  459.     UndoMoveOff(undo->card, (short)COL(undo->from), 1);
  460.     break;
  461.       case U_FROMSTOCK:
  462.     UndoFromStock();
  463.     break;
  464.     }
  465.  
  466.     undoinfo = undoinfo->next;
  467.     free(undo);
  468.  
  469.     return;
  470. }
  471.  
  472.  
  473. void UndoMove(unsigned char card, short col, unsigned char expose)
  474. {
  475.     unsigned char c, row;
  476.     short oldcol;
  477.  
  478.     oldcol = COL(cards[card]);
  479.     c = column[oldcol];
  480.     if (c == card) {
  481.     column[oldcol] = NOCARD;
  482.     } else {
  483.     while (next[c] != card)
  484.         c = next[c];
  485.     next[c] = NOCARD;
  486.     }
  487.  
  488.     c = column[col];
  489.     row = 0;
  490.     if (c == NOCARD) {
  491.     column[col] = card;
  492.     cards[card] = POSN(col, row);
  493.     c = next[card];
  494.     } else {
  495.     while (next[c] != NOCARD) {
  496.         c = next[c];
  497.         row++;
  498.     }
  499.     if (expose)
  500.         hidden[c] = 1;
  501.     next[c] = card;
  502.     cards[card] = POSN(col, ++row);
  503.     c = next[card];
  504.     }
  505.     while (c != NOCARD) {
  506.     cards[c] = POSN(col, ++row);
  507.     c = next[c];
  508.     }
  509.     DisplayColumn(oldcol);
  510.     DisplayColumn(col);
  511.  
  512.     return;
  513. }
  514.  
  515.  
  516. void UndoMoveOff(unsigned char card, short col, unsigned char expose)
  517. {
  518.     unsigned char c, row;
  519.  
  520.     c = column[col];
  521.     row = 0;
  522.     if (c == NOCARD) {
  523.     column[col] = card;
  524.     c = card;
  525.     while (c != NOCARD) {
  526.         cards[c] = POSN(col, row++);
  527.         c = next[c];
  528.     }
  529.     } else {
  530.     while (next[c] != NOCARD) {
  531.         c = next[c];
  532.         row++;
  533.     }
  534.     if (expose)
  535.         hidden[c] = 1;
  536.     next[c] = card;
  537.     c = next[c];
  538.     while (c != NOCARD) {
  539.         cards[c] = POSN(col, row++);
  540.         c = next[c];
  541.     }
  542.     }
  543.     if (foundation[SUIT(card) + 4])
  544.     foundation[SUIT(card) + 4] = 0;
  545.     else
  546.     foundation[SUIT(card)] = 0;
  547.     DisplayColumn((short)col);
  548.     DisplayFoundations();
  549.  
  550.     return;
  551. }
  552.  
  553.  
  554. void UndoFromStock()
  555. {
  556.     unsigned char oldstock = stock;
  557.     unsigned char c;
  558.     short col;
  559.  
  560.     for (col = COLUMNS - 1; col >= 0; col--) {
  561.     c = column[col];
  562.     while (next[next[c]] != NOCARD) {
  563.         c = next[c];
  564.     }
  565.     next[next[c]] = stock;
  566.     stock = next[c];
  567.     cards[stock] = POSN(STOCK, 0);
  568.     next[c] = NOCARD;
  569.  
  570.     DisplayColumn((short)col);
  571.     }
  572.  
  573.     if (oldstock == NOCARD)
  574.     DisplayStockPile();
  575.  
  576.     return;
  577. }
  578.